#pragma once

#include "Log.hpp"
#include <iostream>
#include <string>
#include <set>
#include <cstdio>

const std::string sep = " ";

class Command
{
private:
    // 加载配置文件
    void LoadConf(const std::string &conf)
    {
        std::ifstream ifs(conf);

        if (!ifs.is_open())
        {
            LOG(ERROR, "open file %s failed\n", conf.c_str());
            return;
        }

        std::string line;
        while (std::getline(ifs, line))
        {
            LOG(DEBUG, "line:%s\n", line.c_str());
            _safe_cmd.insert(line);
        }
        ifs.close();
    }

public:
    Command(const std::string &cond_path)
        : _cond_path(cond_path)
    {
        LoadConf(cond_path);
    }

    // touch 1.txt 得到空格前命令
    std::string PrefixCommand(const std::string &cmd)
    {

        if (cmd.empty())
            return std::string();

        auto pos = cmd.find(sep);
        if (pos == std::string::npos)
            return cmd;
        else
            return cmd.substr(0, pos);
    }

    // 判断cmd是否安全
    bool SafeCheck(const std::string &cmd)
    {
        std::string prefix = PrefixCommand(cmd);
        auto iter = _safe_cmd.find(prefix);
        if (iter == _safe_cmd.end())
            return false;
        else
            return true;
    }

    std::string Excute(const std::string &cmd)
    {
        std::string result;
        if (SafeCheck(cmd))
        {
            FILE *fd = popen(cmd.c_str(), "r");

            if (fd == nullptr)
            {
                return "failed";
            }

            char buf[1024];
            while (fgets(buf, sizeof(buf), fd) != nullptr)
            {
                result += buf;
            }

            pclose(fd);
        }
        else
        {
            result = "不安全命令\n";
        }

        return result;
    }

     ~Command()
    {
        _safe_cmd.clear();
    }
private:
    std::set<std::string> _safe_cmd;
    std::string _cond_path;
};
